package com.ruoyi.related_links.domain;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;

import java.time.LocalDateTime;

/**
 * 爬虫进度跟踪实体
 *
 * @author lzk
 * @date 2025-06-24
 */
@Schema(description = "爬虫进度跟踪实体")
public class CrawlerProgress {

    /** 批次大小 */
    public static final int BATCH_SIZE = 50;

    /** 物理主键 */
    @Schema(title = "物理主键")
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    /** 任务ID */
    @Schema(title = "任务ID", description = "唯一标识爬虫任务的ID")
    private String taskId;

    /** 总数量 */
    @Schema(title = "总数量", description = "需要处理的链接总数量")
    private int totalCount;

    /** 已处理数量 */
    @Schema(title = "已处理数量", description = "已经处理完成的链接数量")
    private int processedCount;

    /** 成功数量 */
    @Schema(title = "成功数量", description = "处理成功的链接数量")
    private int successCount;

    /** 失败数量 */
    @Schema(title = "失败数量", description = "处理失败的链接数量")
    private int failureCount;

    /** 当前批次 */
    @Schema(title = "当前批次", description = "正在处理的批次编号")
    private int currentBatch;

    /** 总批次数 */
    @Schema(title = "总批次数", description = "需要处理的批次总数")
    private int totalBatches;

    /** 状态: RUNNING, COMPLETED, ERROR */
    @Schema(title = "任务状态", description = "任务执行状态：RUNNING-运行中, COMPLETED-已完成, ERROR-错误")
    private String status;

    /** 当前处理项 */
    @Schema(title = "当前处理项", description = "正在处理的链接URL或描述")
    private String currentProcessing;

    /** 开始时间 */
    @Schema(title = "开始时间", description = "任务开始执行的时间")
    private LocalDateTime startTime;

    /** 结束时间 */
    @Schema(title = "结束时间", description = "任务结束的时间")
    private LocalDateTime endTime;

    /** 错误信息 */
    @Schema(title = "错误信息", description = "任务执行过程中的错误信息")
    private String errorMessage;

    /**
     * 默认构造函数
     */
    public CrawlerProgress() {
    }

    /**
     * 构造函数
     *
     * @param taskId 任务ID
     * @param totalCount 总数量
     */
    public CrawlerProgress(String taskId, int totalCount) {
        this.taskId = taskId;
        this.totalCount = totalCount;
        this.totalBatches = (int) Math.ceil((double) totalCount / BATCH_SIZE);
        this.status = "RUNNING";
        this.startTime = LocalDateTime.now();
        this.processedCount = 0;
        this.successCount = 0;
        this.failureCount = 0;
        this.currentBatch = 1;
    }

    /**
     * 计算进度百分比
     *
     * @return 进度百分比
     */
    @Schema(title = "进度百分比", description = "任务完成的百分比")
    public double getProgressPercentage() {
        return totalCount == 0 ? 0.0 : (double) processedCount / totalCount * 100;
    }

    /**
     * 增加成功计数
     */
    public void incrementSuccessCount() {
        this.successCount++;
        this.processedCount++;
    }

    /**
     * 增加失败计数
     */
    public void incrementFailureCount() {
        this.failureCount++;
        this.processedCount++;
    }

    /**
     * 更新当前批次
     *
     * @param batchNumber 批次编号
     */
    public void updateCurrentBatch(int batchNumber) {
        this.currentBatch = batchNumber;
    }

    /**
     * 完成任务
     */
    public void complete() {
        this.status = "COMPLETED";
        this.endTime = LocalDateTime.now();
        this.currentProcessing = "爬取完成";
    }

    /**
     * 标记错误
     *
     * @param errorMessage 错误信息
     */
    public void markError(String errorMessage) {
        this.status = "ERROR";
        this.endTime = LocalDateTime.now();
        this.errorMessage = errorMessage;
        this.currentProcessing = "爬取出错";
    }

    /**
     * 检查任务是否完成
     *
     * @return true如果任务完成
     */
    public boolean isCompleted() {
        return "COMPLETED".equals(status) || "ERROR".equals(status);
    }

    /**
     * 检查任务是否正在运行
     *
     * @return true如果任务正在运行
     */
    public boolean isRunning() {
        return "RUNNING".equals(status);
    }

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public int getProcessedCount() {
        return processedCount;
    }

    public void setProcessedCount(int processedCount) {
        this.processedCount = processedCount;
    }

    public int getSuccessCount() {
        return successCount;
    }

    public void setSuccessCount(int successCount) {
        this.successCount = successCount;
    }

    public int getFailureCount() {
        return failureCount;
    }

    public void setFailureCount(int failureCount) {
        this.failureCount = failureCount;
    }

    public int getCurrentBatch() {
        return currentBatch;
    }

    public void setCurrentBatch(int currentBatch) {
        this.currentBatch = currentBatch;
    }

    public int getTotalBatches() {
        return totalBatches;
    }

    public void setTotalBatches(int totalBatches) {
        this.totalBatches = totalBatches;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getCurrentProcessing() {
        return currentProcessing;
    }

    public void setCurrentProcessing(String currentProcessing) {
        this.currentProcessing = currentProcessing;
    }

    public LocalDateTime getStartTime() {
        return startTime;
    }

    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }

    public LocalDateTime getEndTime() {
        return endTime;
    }

    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
}